package com.example.accessingdatajpa.service.impl;

import com.example.accessingdatajpa.exception.ResourceNotFoundException;
import com.example.accessingdatajpa.pojo.Customer;
import com.example.accessingdatajpa.pojo.ShoppingCart;
import com.example.accessingdatajpa.repository.ShoppingCartRepository;
import com.example.accessingdatajpa.response.RestResponse;
import com.example.accessingdatajpa.service.IShoppingCartService;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Service("shoppingCartService")
public class ShoppingCartServiceImpl implements IShoppingCartService {
    @Autowired
    private ShoppingCartRepository shoppingCartRepository;

    //find all goods in shopping cart by id
    @Override
    @Transactional
    public RestResponse<List<ShoppingCart>> queryAllInShoppingCartById(Long customerId){
        RestResponse<List<ShoppingCart>> response = new RestResponse<>();
        try {
            List<ShoppingCart> data = shoppingCartRepository.findByCustomer_CustomerId(customerId);
            response.setStatus(200);
            response.setMessage("查询成功");
            response.setData(data);
        }catch (RuntimeException e){
            response.setStatus(500);
            response.setMessage(e.getMessage());
        }
        return response;
    }
    //find all goods in order management or shopping cart
    //isSubmit为true显示的是订单中的全部商品，false时显示的是购物车中的全部商品
    @Override
    @Transactional
    public RestResponse<List<ShoppingCart>> queryAllGoodsInOM(Long customerId, Boolean isSubmit){
        RestResponse<List<ShoppingCart>> response = new RestResponse<>();
        try {
            List<ShoppingCart> data = shoppingCartRepository.findByCustomer_CustomerIdAndIsSubmit(customerId, isSubmit);
            response.setStatus(200);
            response.setMessage("查询成功");
            response.setData(data);
        }catch (RuntimeException e){
            response.setStatus(500);
            response.setMessage(e.getMessage());
        }
        return response;
    }

    //find all goods in order management or shopping cart(cookie实验版本)
    //isSubmit为true显示的是订单中的全部商品，false时显示的是购物车中的全部商品
    @Override
    @Transactional
    public RestResponse<List<ShoppingCart>> queryGoodsInOM(Long customerId, Boolean isSubmit, HttpServletRequest request, HttpServletResponse rep){
        RestResponse<List<ShoppingCart>> response = new RestResponse<>();
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            Cookie[] cookies = request.getCookies();
            List<ShoppingCart> data;
            if (customerId==22){//未登录状态，暂定为22
                data = new ArrayList<>();
                for (Cookie cookie:cookies){
                    new ShoppingCart();
                    ShoppingCart shoppingCart;
                    shoppingCart = objectMapper.readValue(URLDecoder.decode(cookie.getValue(), StandardCharsets.UTF_8), ShoppingCart.class);
                    data.add(shoppingCart);
                    System.out.println(shoppingCart);
                }
            }else {
                data = shoppingCartRepository.findByCustomer_CustomerIdAndIsSubmit(customerId, isSubmit);
            }
            response.setStatus(200);
            response.setMessage("查询成功");
            response.setData(data);

        }catch (RuntimeException e){
            response.setStatus(500);
            response.setMessage(e.getMessage());
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return response;
    }

    //find goods in order management
    //order management为0时是提交订单未付款，为1时是付款未提货，为2时是已提货
    @Override
    @Transactional
    public RestResponse<List<ShoppingCart>> queryGoodsInOM(Long customerId, Integer orderManagement){
        RestResponse<List<ShoppingCart>> response = new RestResponse<>();
        try {
            List<ShoppingCart> data = shoppingCartRepository.findByCustomer_CustomerIdAndIsSubmitAndOrderManagement(customerId,true,orderManagement);
            response.setStatus(200);
            response.setMessage("查询成功");
            response.setData(data);
        }catch (RuntimeException e){
            response.setStatus(500);
            response.setMessage(e.getMessage());
        }
        return response;
    }

    //add new goods in shopping cart
    //新添加商品时添加至为isSubmit为false的字段
    @Override
    @Transactional
    public RestResponse<String> addInShoppingCart(ShoppingCart shoppingCart, Long customerId){
        RestResponse<String> response = new RestResponse<>();
        try {
            if (shoppingCartRepository.findByGoodsTitleAndCustomer_CustomerIdAndIsSubmit(shoppingCart.getGoodsTitle(),customerId,false)!=null){
                //如果标题重复，且为购物车中，而非订单中的字段，则找到该字段，使其数量增加
                ShoppingCart shoppingCart2 = shoppingCartRepository.findByGoodsTitleAndCustomer_CustomerIdAndIsSubmit(shoppingCart.getGoodsTitle(), customerId,false);
                shoppingCart2.setGoodsAmount(shoppingCart2.getGoodsAmount()+shoppingCart.getGoodsAmount());
                //重新计算总价格
                BigDecimal amount = new BigDecimal(Long.toString(shoppingCart2.getGoodsAmount()));
                BigDecimal price = new BigDecimal(Double.toString(shoppingCart2.getUnitPrice()));
                shoppingCart2.setTotalValue(amount.multiply(price).toString());
                shoppingCartRepository.save(shoppingCart2);
            }else {
                //先新建一个customer对象，保存customer至shoppingCart的customer属性中，最后再保存该shoppingCart
                Customer customer = new Customer();
                customer.setCustomerId(customerId);
                shoppingCart.setCustomer(customer);
                BigDecimal amount = new BigDecimal(Long.toString(shoppingCart.getGoodsAmount()));
                BigDecimal price = new BigDecimal(Double.toString(shoppingCart.getUnitPrice()));
                shoppingCart.setTotalValue(amount.multiply(price).toString());
                shoppingCartRepository.save(shoppingCart);
            }
            response.setStatus(200);
            response.setMessage("ok");
            response.setData("保存成功");
        }catch (RuntimeException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            response.setStatus(500);
            response.setMessage(e.getMessage());
        }
        return response;
    }

    //add new goods in shopping cart(cookie实验版本)
    //新添加商品时添加至为isSubmit为false的字段
    @Override
    @Transactional
    public RestResponse<String> addShoppingCart(ShoppingCart shoppingCart, Long customerId, HttpServletRequest request, HttpServletResponse rep){
        RestResponse<String> response = new RestResponse<>();
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            Cookie[] cookies = request.getCookies();
//            for(Cookie cookie:cookies) {//清空cookies
//                cookie.setMaxAge(0);
//                cookie.setPath("/");
//                rep.addCookie(cookie);
//            }

            //未登录状态（成功添加，但不完全成功，可能和cookie的path以及存活时间有关）
            if (customerId==22){//暂定为22，需要前端传入是否登录的数据
                int count = 0;//计算循环次数，每次循环后重置
                Writer writer = new StringWriter();
                if (cookies!=null){
                    for (Cookie cookie:cookies){//遍历目前的cookie列表
                        new ShoppingCart();//由于cookie的命名存在规则，故要想判断是否存在一致的名称，需要先提取到实体中（能否实现待定）
                        ShoppingCart shoppingCart2;
                        shoppingCart2 = objectMapper.readValue(URLDecoder.decode(cookie.getValue(), StandardCharsets.UTF_8), ShoppingCart.class);//将中文解码
                        if (shoppingCart.getGoodsTitle().equals(shoppingCart2.getGoodsTitle())){//在cookie转换后得到的列表中找到相同名称的商品，进行数量的叠加，并覆盖
                            shoppingCart2.setGoodsAmount(shoppingCart2.getGoodsAmount()+shoppingCart.getGoodsAmount());//重置商品数量
                            double totalValue = shoppingCart2.getUnitPrice()*shoppingCart2.getGoodsAmount();//重新计算商品总价
                            shoppingCart2.setTotalValue(Double.toString(totalValue));//保存商品总价
                            objectMapper.writeValue(writer,shoppingCart2);
                            cookie.setValue(URLEncoder.encode(writer.toString(), StandardCharsets.UTF_8));//重新写入cookie
//                            cookie.setPath("/");
//                            cookie.setMaxAge(60);
                            rep.addCookie(cookie);
                            break;
                        }
                        count++;//每循环一次，进行计数
                    }
                }
                if (cookies==null||count==cookies.length){//循环次数与cookie列表长度一致，说明原cookie列表中不存在该商品
                    System.out.println(count);
                    System.out.println((cookies!=null)?cookies.length:"null");
                    objectMapper.writeValue(writer,shoppingCart);
                    //原cookie列表中不存在该项，新建cookie保存商品，中文进行编码
                    Cookie cookie = new Cookie(shoppingCart.getUnitPrice().toString(), URLEncoder.encode(writer.toString(), StandardCharsets.UTF_8));
                    cookie.setPath("/");
                    cookie.setMaxAge(2*60);
                    rep.addCookie(cookie);
                }
                //已登录状态（成功，可以实现全部功能）
            }
            else {
                //判断cookie列表是否为空
                if (cookies!=null){//不为空，将cookie中的商品加入数据表（持久层购物车）
                    List<ShoppingCart> shoppingCarts = shoppingCartRepository.findAll();//查询当前数据表中的商品
                    int shoppingSize=shoppingCarts.size();//购物车中的商品数量
                    for (Cookie cookie : cookies)//加强的for循环，用来遍历cookie中的商品
                    {
                        int count=0;//每次内循环结束，重置计数
                        new ShoppingCart();
                        ShoppingCart shoppingCart2;//新建对象
                        shoppingCart2 = objectMapper.readValue(URLDecoder.decode(cookie.getValue(), StandardCharsets.UTF_8),ShoppingCart.class);//将cookie中的json字符串取出，以对象类型输入
                        for (ShoppingCart shoppingCart1:shoppingCarts)//加强的for循环，用来遍历当前数据表中的商品
                        {
                            if (shoppingCart1.getGoodsTitle().equals(shoppingCart2.getGoodsTitle())){//列表中的商品与cookie中的商品有重复现象的情况
                                hasSameOrNot(shoppingCart1.getGoodsTitle(),customerId,shoppingCart2);//自定义函数向购物车中进行商品数量的合并
                                break;//若找到，则跳出内循环
                            }
                            count++;//计数
                        }
                        if (count==shoppingSize){//如果计数结果与原来购物车中商品数量一致，说明原来购物车中不存在该商品，新建字段保存商品
                            new ShoppingCart();
                            ShoppingCart shoppingCart1;
                            shoppingCart1 = objectMapper.readValue(URLDecoder.decode(cookie.getValue(), StandardCharsets.UTF_8), ShoppingCart.class);//将cookie中的json字符串取出，以对象类型输入
                            Customer customer = new Customer();
                            customer.setCustomerId(customerId);
                            shoppingCart1.setCustomer(customer);
                            shoppingCartRepository.save(shoppingCart1);//保存至购物车
                    }

                }
                    //全部保存过后，清空cookie，立马销毁
                    Cookie cookie = new Cookie(shoppingCart.getUnitPrice().toString(), null);
                    cookie.setPath("/");
                    cookie.setMaxAge(-0);
                    rep.addCookie(cookie);
                }else {//cookie中商品为空，直接将商品存入数据表（持久层购物车）
                    hasSameOrNot(shoppingCart.getGoodsTitle(),customerId,shoppingCart);
                }
            }
            response.setStatus(200);
            response.setMessage("ok");
            response.setData("保存成功");
        }catch (RuntimeException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            response.setStatus(500);
            response.setMessage(e.getMessage());
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
        return response;
    }

    //update the account of goods and re-calculate the total value
    @Override
    @Transactional
    public RestResponse<String> updateAccountInCartById(Long shoppingId, Long goodsAmount){
        RestResponse<String> response = new RestResponse<>();
        try {
            shoppingCartRepository.updateGoodsAmount(goodsAmount,shoppingId);
            //计算总价格
            ShoppingCart shoppingCart = shoppingCartRepository.findById(shoppingId)
                    .orElseThrow(() -> new ResourceNotFoundException("ShoppingCart","id",shoppingId));
            BigDecimal amount1 = new BigDecimal(Long.toString(shoppingCart.getGoodsAmount()));
            BigDecimal price1 = new BigDecimal(Double.toString(shoppingCart.getUnitPrice()));
            shoppingCart.setTotalValue(amount1.multiply(price1).toString());
            shoppingCartRepository.save(shoppingCart);
            response.setStatus(200);
            response.setMessage("ok");
            response.setData("更新成功");
        }catch (RuntimeException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//捕获了异常但未抛出，手动抛出
            response.setStatus(500);
            response.setMessage(e.getMessage());
        }
        return response;
    }

    //select the goods or not
    @Override
    @Transactional
    public RestResponse<String> chooseGoods(Long shoppingId,Boolean goodsSelect){
        RestResponse<String> response = new RestResponse<>();
        try {
            shoppingCartRepository.updateGoodsSelect(goodsSelect,shoppingId);
            response.setStatus(200);
            response.setMessage("ok");
            response.setData("更新成功");
        }catch (RuntimeException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            response.setStatus(500);
            response.setMessage(e.getMessage());
        }
        return response;
    }

    //order management
    @Override
    @Transactional
    public RestResponse<String> manageOrder(Long shoppingId, Boolean isSubmit, Integer orderManagement){
        RestResponse<String> response = new RestResponse<>();
        try {
            ShoppingCart shoppingCart = shoppingCartRepository.findById(shoppingId)
                    .orElseThrow(() -> new ResourceNotFoundException("ShoppingCart","id",shoppingId));
            shoppingCart.setSubmit((isSubmit==null)?shoppingCart.getSubmit():isSubmit);
            shoppingCart.setOrderManagement((orderManagement==null)?shoppingCart.getOrderManagement():orderManagement);
            response.setStatus(200);
            response.setMessage("ok");
            response.setData("更新成功");
        }catch (RuntimeException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            response.setStatus(500);
            response.setMessage(e.getMessage());
        }
        return response;
    }

    //change batch


    //delete goods by id
    @Override
    @Transactional
    public RestResponse<String> deleteGoods(Long shoppingId){
        RestResponse<String> response = new RestResponse<>();
        try {
            ShoppingCart shoppingCart = shoppingCartRepository.findById(shoppingId)
                    .orElseThrow(() -> new ResourceNotFoundException("ShoppingCart","id",shoppingId));
            shoppingCartRepository.delete(shoppingCart);
            response.setStatus(200);
            response.setMessage("ok");
            response.setData("delete success");
        }catch (RuntimeException e){
            response.setStatus(500);
            response.setMessage(e.getMessage());
        }
        return response;
    }

    //判断是否新建商品字段的函数
    public void hasSameOrNot(String goodsTitle,Long customerId,ShoppingCart shoppingCart){
        if (shoppingCartRepository.findByGoodsTitleAndCustomer_CustomerIdAndIsSubmit(goodsTitle,customerId,false)!=null){
            //如果标题重复，且为购物车中，而非订单中的字段，则找到该字段，使其数量增加
            ShoppingCart shoppingCart2 = shoppingCartRepository.findByGoodsTitleAndCustomer_CustomerIdAndIsSubmit(goodsTitle, customerId,false);
            shoppingCart2.setGoodsAmount(shoppingCart2.getGoodsAmount()+shoppingCart.getGoodsAmount());
            //重新计算总价格
            BigDecimal amount = new BigDecimal(Long.toString(shoppingCart2.getGoodsAmount()));
            BigDecimal price = new BigDecimal(Double.toString(shoppingCart2.getUnitPrice()));
            shoppingCart2.setTotalValue(amount.multiply(price).toString());
            shoppingCartRepository.save(shoppingCart2);
        }else {
            //先新建一个customer对象，保存customer至shoppingCart的customer属性中，最后再保存该shoppingCart
            Customer customer = new Customer();
            customer.setCustomerId(customerId);
            shoppingCart.setCustomer(customer);
            BigDecimal amount = new BigDecimal(Long.toString(shoppingCart.getGoodsAmount()));
            BigDecimal price = new BigDecimal(Double.toString(shoppingCart.getUnitPrice()));
            shoppingCart.setTotalValue(amount.multiply(price).toString());
            shoppingCartRepository.save(shoppingCart);
        }
    }
}
